package date;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Date;

/**
 * @author DCSGO
 * @version 1.0
 * 第三代日期类
 * LocalDate 日期
 * LocalTime 时间
 * LocalDateTime 日期和时间
 * Instant 时间戳
 */
public class Date03 {
    //JDK 1.0中包含了一个 java.util.Date 类 但是它的大多数方法已经在JDK 1.1 引入
    //Calendar 类之后被弃用了 而 Calendar 也存在一些问题:
    //1.可变性: 像日期和时间这样的类应该是不变的
    //2.偏移性: Date 中的年份是从1900开始的 而月份从0开始
    //3.格式化: 格式化只对 Date 有用 Calendar 则不行
    //4.它们也不是线程安全的 不能处理闰秒(每隔2天 多出1秒)等

    public static void main2(String[] args) {
        /*
         * Instant 和 Date 都是用于表示日期和时间的类 但在Java中 它们有一些区别和联系
         *
         * 区别:
         * 1.类型: Instant 是 Java 8 中新引入的类 位于 java.time 包中 而 Date 是旧的日期类 位于 java.util 包中
         * 2.可变性: Instant 是不可变的 一旦创建就不能修改 而 Date 是可变的 可以通过一些方法修改日期和时间的值
         * 3.精度: Instant 包含纳秒级别的精度 可以表示比 Date 更细致的时间 Date 只能表示毫秒级别的精度
         * 4.时区处理: Instant 以格林威治标准时间(UTC) 为基准 无法直接表示其他时区的日期和时间 需要进行时区转换
         *    而 Date 可以表示其他时区的日期和时间 但处理时区比较繁琐
         *
         * 联系:
         * 1.互相转换: 可以通过 toInstant() 方法将 Date 转换为 Instant 或通过 from() 方法将 Instant 转换为 Date
         * 2.共享操作: Instant 和Date 都提供了一些共同的操作方法 如获取年份 月份 日 小时 分钟 秒等
         *
         * 总的来说 Instant 是 Java 8 中更加现代化和推荐的日期和时间类 它提供了更好的精度和时区处理能力 如果在新的 Java 项目中
         * 尽量使用 Instant 来表示日期和时间 如果与遗留代码或旧的Java库有交互 可能需要进行 Instant 和 Date 之间的转换
         */

        Date date = new Date();
        System.out.println(date);//Thu Jun 29 14:15:35 CST 2023

        Instant instant = Instant.now();
        System.out.println(instant);//2023-06-29T06:15:35.418Z

        //将 instant 对象转换成 Date 对象
        Date date1 = Date.from(instant);
        System.out.println(date1);//Thu Jun 29 14:17:36 CST 2023

        //将 Date 对象转换成 Instant 对象
        Instant instant1 = date.toInstant();
        System.out.println(instant1);//2023-06-29T06:17:36.626Z
    }

    public static void main(String[] args) {
        //LocalDate 日期 LocalTime 时间 LocalDateTime 日期和时间
        //1.实例化一个 日期和时间
        LocalDateTime ldt = LocalDateTime.now();//返回一个系统当前日期和时间的对象
        System.out.println(ldt);//2023-06-27T17:13:43.375

        //2.获取 年 月 日 时 分 秒
        System.out.println("年: " + ldt.getYear());
        System.out.println("月: " + ldt.getMonthValue());
        System.out.println("日: " + ldt.getDayOfMonth());
        System.out.println("时: " + ldt.getHour());
        System.out.println("分: " + ldt.getMinute());
        System.out.println("秒: " + ldt.getSecond());
        /*
         * 年: 2023
         * 月: 6
         * 日: 27
         * 时: 17
         * 分: 17
         * 秒: 14
         */

        System.out.println(ldt.getMonth());//JUNE

        //3.格式化输出日期
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy年MM月dd日 E HH:mm:ss");
        String pattern = dtf.format(ldt);
        System.out.println(pattern);//          2023年06月29日 星期四 14:06:47

        //4.第三带日期类 更多方法
        //时间的加减(年 月 日 星期 时 分 秒 纳秒)
        LocalDateTime plus = ldt.plusHours(1024);
        System.out.println(dtf.format(plus));// 2023年08月11日 星期五 06:24:52

        LocalDateTime minus = ldt.minusHours(1024);
        System.out.println(dtf.format(minus));//2023年05月17日 星期三 22:26:15

        //是否是闰年
        System.out.println(Year.isLeap(ldt.getYear()));//false
        for (int i = 0; i <= 40; i++) {
            if (i % 10 == 0) {
                System.out.println();
            }
            Year year = Year.of(ldt.plusYears(i).getYear());
            System.out.print(year + " " + Year.isLeap(year.getValue()) + " ");
        }
        /*
         * 2023 false 2024 true 2025 false 2026 false 2027 false 2028 true 2029 false 2030 false 2031 false 2032 true
         * 2033 false 2034 false 2035 false 2036 true 2037 false 2038 false 2039 false 2040 true 2041 false 2042 false
         * 2043 false 2044 true 2045 false 2046 false 2047 false 2048 true 2049 false 2050 false 2051 false 2052 true
         * 2053 false 2054 false 2055 false 2056 true 2057 false 2058 false 2059 false 2060 true 2061 false 2062 false
         * 2063 false
         */

        System.out.println("\n");

        //MonthDay 类
        //在Java中 MonthDay类用于表示不包含年份的月份和日期
        //MonthDay类的主要作用是在不需要关注具体年份的情况下
        //对月份和日期进行操作和比较 它具有以下功能和用途：

        //1.创建MonthDay对象: 可以使用 MonthDay.of() 方法创建一个 MonthDay对象 指定月份和日期
        MonthDay holiday = MonthDay.of(Month.DECEMBER, 25); //圣诞节

        //2.获取月份和日期: 可以使用 getMonth() 和 getDayOfMonth() 方法分别获取 MonthDay 对象的月份和日期值
        Month month = holiday.getMonth();
        int day = holiday.getDayOfMonth();

        //3.判断相等性: 可以使用 equals() 方法来判断两个 MonthDay 对象是否相等
        MonthDay birthday = MonthDay.of(Month.MARCH, 15);
        if (birthday.equals(holiday)) {
            System.out.println("It's your birthday!");
        }

        //4.比较月份和日期: MonthDay类实现了 Comparable<MonthDay> 接口
        //  可以使用 compareTo() 方法来比较两个 MonthDay 对象的先后顺序
        if (birthday.compareTo(holiday) < 0) {
            System.out.println("Your birthday is before the holiday.");
        } else {
            System.out.println("Your birthday is after the holiday.");
        }
        //Your birthday is before the holiday.

        //总的来说 MonthDay类提供了一种简单且方便的方法来处理只包含月份和日期的情况
        //它可以用于日历事件 周期性的提醒 节日计算等场景
    }
}
